package com.googlecode.lightest.core

class TaskResult implements ITaskResult {
    ITask task
    ITaskResult parentResult
    List<ITaskResult> childResults
    String message
    String responseData
    List<String> links
    int status
    long startTime
    long endTime

    /**
     * Constructs a default task result. The default status is always
     * ITaskResult.STATUS_OK .
     */
    TaskResult(ITask task) {
        this(task, null)
    }
    
    TaskResult(ITask task, ITaskResult parentResult) {
        this.task = task
        this.parentResult = parentResult
        childResults = []
        message = ""
        responseData = ""
        links = []
        status = STATUS_OK
        
        if (parentResult != null) {
            parentResult.appendChild(this)
        }
    }
    
    /**
     * Returns a message describing the result.
     */
    String getMessage() {
        return message
    }
    
    /**
     * Returns the data generated when performing the task, if any.
     */
    String getResponseData() {
        return responseData
    }
    
    /**
     * Returns the list of URL's associated with this result.
     */
    List<String> getLinks() {
        return links
    }
    
    /**
     * Returns the status of the result.
     */
    int getStatus() {
        return status
    }
    
    /**
     * Returns the task whose performance returned this result.
     */
    ITask getTask() {
        return task
    }
    
    /**
     * Returns the time the task was started.
     */
    long getStartTime() {
        return startTime
    }
    
    /**
     * Returns the time the task was finished.
     */
    long getEndTime() {
        return endTime
    }
    
    /**
     * Sets the return value of getMessage().
     *
     * @param message
     */
    void setMessage(String message) {
        this.message = message
    }
    
    /**
     * Sets the return value of getResponseData().
     *
     * @param message
     */
    void setResponseData(String responseData) {
        this.responseData = responseData
    }
    
    /**
     * Adds a URL referencing a resource that provides additional information
     * related to this result.
     * 
     * @param link  the string representation of the URL to add
     */
    void addLink(String link) {
        links << link
    }
    
    /**
     * Sets the time the task was started.
     */
    void setStartTime(long startTime) {
        this.startTime = startTime
    }
    
    /**
     * Sets the time the task was finished.
     */
    void setEndTime(long endTime) {
        this.endTime = endTime
    }
    
    /**
     * Sets the parent task result.
     * 
     * @param parentResult
     */
    void setParent(ITaskResult parentResult) {
        this.parentResult = parentResult
    }
    
    /**
     * Returns the parent task result.
     */
    ITaskResult parent() {
        return parentResult
    }
    
    /**
     * Adds to the list of child task results.
     */
    void appendChild(ITaskResult childResult) {
        childResults << childResult
    }
    
    /**
     * Returns a list of child task results.
     */
    List<ITaskResult> children() {
        return childResults
    }
    
    /**
     * Sets the status of this result to STATUS_FLAGGED, but only if it is not
     * already STATUS_FAILED. The default status of the task should be
     * STATUS_OK.
     */
    void flag() {
        setStatus(STATUS_FLAGGED)
    }
    
    /**
     * Sets the status of this result to STATUS_FAILED, but only if it is not
     * already STATUS_DOOMED. The default status of the task should be
     * STATUS_OK.
     */
    void fail() {
        setStatus(STATUS_FAILED)
    }
    
    /**
     * Sets the status of this result to STATUS_DOOMED, which indicates that
     * the failure of the task means the remainder of the test cannot
     * continue successfully, and should be aborted.
     */
    void doom() {
        setStatus(STATUS_DOOMED)
    }
    
    protected void setStatus(newStatus) {
        if (status < newStatus) {
            status = newStatus
        }
        parentResult?.setStatus(newStatus)
    }
}
